import { Form, FormItem, Row, Col } from 'ant-design-vue'
import { defineComponent, ref } from "vue";

/**
 * 动态查询表单
 * 文档：query-form.md
 * 链接：http://note.youdao.com/noteshare?id=e52f95d9baa33ab53ddba2474e05b2dd&sub=BAD87EC1F7664ECE88115A89AD7B7B76
 */
export default defineComponent({
  name: "query-form",
  props: {
    model: { // 表单中已有的字段，必须出现在 form 对象里，否则不会实现双向绑定
      type: Object,
      default: () => ({})
    },
    fields: { // 字段列表
      type: Array,
      required: true,
      // demo: {
      //   label: null, // 表单项文案
      //   prop: null, // 字段名
      //   domType: null, // 表单元素类型，a-input | a-select 等
      //   domProps: null, // 表单元素 props
      //   placeholder: null, // 描述
      //   formItemProps: null, // 表单项 props
      // }
    },
    col: {
      type: Number,
      default: 1
    }
  },
  /**
   * fieldItem.render 方法必须使用匿名函数。否则需要做如下改变：
   *  1.render() 要写成 render(h)
   *  2.fieldItem.render?.(h)
   *  3.在外边的 render 中也要接收 h，即使不用它
   * 在 jsx 中，使用 form-model 会报 input undefined 错误，需要手动加上：onInput
   * @return {JSX.Element}
   */
  setup (props, { attrs }) {
    const needRowDom = props.col && attrs.layout !== 'inline'
    const colSpan = 24 / props.col
    const formRef = ref()
    function renderInput (fieldItem) {
      return (
        <fieldItem.domType
          value={props.model[fieldItem.prop]}
          placeholder={fieldItem.placeholder}
          {...fieldItem.domProps}
          domProps={fieldItem.domNativeProps}
          onChange={e => {
            const isEvent = e instanceof Event
            this.model[fieldItem.prop] = isEvent ? e.target.value : e
          }}
        />
      )
    }
    return (
      <Form
        ref={formRef}
        {...Object.assign({ model: props.model }, attrs)}
        onInput={() => {}}
      >
        {
          needRowDom
            ? (
              <a-row>
                {
                  this.fields.map(fieldItem => (
                    <Row span={colSpan} {...fieldItem.colProps}>
                      <FormItem
                        label={fieldItem.label}
                        prop={fieldItem.prop} {...fieldItem.formItemProps}
                      >
                        {fieldItem.render?.(props.model[fieldItem.prop], props.model, fieldItem) ?? renderInput(fieldItem)}
                      </FormItem>
                    </Row>
                  ))
                }
              </a-row>
            )
            : (
              this.fields.map(fieldItem => (
                <FormItem label={fieldItem.label} prop={fieldItem.prop} {...{ props: fieldItem.formItemProps }}>
                  {fieldItem.render?.(props.model[fieldItem.prop], props.model, fieldItem) ?? renderInput(fieldItem)}
                </FormItem>
              ))
            )
        }
      </Form>
    )
  }
})
